require 'yaml'
require 'metasploit/command_line_argument_parser'

class ExploitRunDescription
  attr_accessor :connection_url,
    :port,
    :uri,
    :use_ssl,
    :token,
    :workspace_name,
    :nexpose_console_name,
    :device_ip_to_scan,
    :use_os_filter,
    :module_filter,
    :report_type,
    :whitelist_hosts,
    :exploit_speed,
    :limit_sessions

  @@port_value = ''
  @@uri_value = ''
  @@use_ssl_value = ''
  @@device_ip_to_scan_value = ''
  @@use_os_filter_value = ''

  def initialize(options)
    if File.file?('config/exploit.yml')
      options = YAML.load_file('config/exploit.yml')
    elsif options.instance_of? Array
      options = CommandLineArgumentParser.parse(options)
    end

    self.connection_url = options['connection_url']
    @@port_value = options['port']
    @@uri_value = options['uri']
    @@use_ssl_value = options['use_ssl']
    self.token = options['token']
    self.workspace_name = options['workspace_name']
    self.nexpose_console_name = options['nexpose_console_name']
    @@device_ip_to_scan_value = options['device_ip_to_scan']
    self.use_os_filter = options['use_os_filter']
    self.module_filter = options['module_filter']
    self.report_type = options['report_type']
    self.whitelist_hosts = options['whitelist_hosts']
    self.exploit_speed = options['exploit_speed'] || 5
    self.limit_sessions = options['limit_sessions'].nil? ? true : options['limit_sessions']
  end

  def verify
    raise StandardError, CONSTANTS::REQUIRED_TOKEN_MESSAGE if token.nil? || token.empty?
    raise StandardError, CONSTANTS::REQUIRED_CONNECTION_URL_MESSAGE if connection_url.nil? || connection_url.empty?
    raise StandardError, CONSTANTS::REQUIRED_DEVICE_IP_TO_SCAN_MESSAGE if device_ip_to_scan.nil? || device_ip_to_scan.empty?
    raise StandardError, CONSTANTS::REQUIRED_WORKSPACE_MESSAGE if workspace_name.nil? || workspace_name.empty?
  end

  def get_options
    {:host => self.connection_url,
     :port => self.port,
     :token => self.token,
     :uri => self.uri,
     :ssl => self.use_ssl,
     :ssl_version => 'TLS1'
    }
  end

  def device_ip_to_scan=(value)
    if !@@device_ip_to_scan_value.nil?
        @@device_ip_to_scan_value = value.strip!
    end
  end

  def get_audit_options
    { "workspace" => self.workspace_name,
      "DS_URLS" => self.device_ip_to_scan,
      "DS_MAX_REQUESTS" => 1000,
      "DS_MAX_MINUTES" => 3,
      "DS_MAX_THREADS" => 5,
      "DS_MAX_INSTANCES" => 3}
  end

  def get_exploit_options
    { "workspace" => self.workspace_name,
      "DS_WHITELIST_HOSTS" => self.whitelist_hosts,
      "DS_MinimumRank" => "great",
      "DS_EXPLOIT_SPEED" => self.exploit_speed,
      "DS_EXPLOIT_TIMEOUT" => 2,
      "DS_LimitSessions" => self.limit_sessions,
      "DS_MATCH_VULNS" => true,
      "DS_MATCH_PORTS" => true,
      "DS_FilterByOS" => self.use_os_filter,
      "DS_ModuleFilter" => self.module_filter}
  end

  def get_report_options
    {
        'workspace' => self.workspace_name,
        'name' => self.workspace_name,
        'report_type' => self.report_type,
        'created_by' => self.workspace_name,
        'file_formats' => [:pdf],
        'DS_WHITELIST_HOSTS' => self.device_ip_to_scan
    }
  end

  def device_ip_to_scan
    if @@device_ip_to_scan_value.nil? || @@device_ip_to_scan_value.empty?
        return nil
    end
    values = @@device_ip_to_scan_value.split(' ')
    if values.nil? || values.length == 0
        return nil
    end
    ret = []
    values.each do |value|
        ret.push("http://#{value}/")
    end
    ret.join(' ')
  end

  def port=(value)
    @@port_value = value
  end

  def port
    get_value(@@port_value, CONSTANTS::DEFAULT_PORT)
  end

  def uri=(value)
    @@uri_value = value
  end

  def uri
    get_value(@@uri_value, CONSTANTS::DEFAULT_URI)
  end

  def use_ssl=(value)
    @@use_ssl_value = value
  end

  def use_ssl
    (@@use_ssl_value != false) ? true : false
  end

  def use_os_filter=(value)
    @@use_os_filter_value = value
  end

  def use_os_filter
    self.to_bool(@@use_os_filter_value)
  end


  def get_value(value_to_check, default)
    (value_to_check.nil? || value_to_check.empty?) ? default : value_to_check
  end

  def to_bool(str)
    str == true || str == 'true'
  end

end
